package com.smartstate.ems.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.alibaba.nacos.shaded.com.google.gson.GsonBuilder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartstate.ems.core.ScheduleConstants;
import com.smartstate.ems.dto.EquipmentDTO;
import com.smartstate.ems.dto.PageDTO;
import com.smartstate.ems.entity.*;
import com.smartstate.ems.exception.ErrorEnums;
import com.smartstate.ems.exception.MyRException;
import com.smartstate.ems.mapper.*;
import com.smartstate.ems.service.EquipmentService;
import com.smartstate.ems.service.IQuartzJobService;
import com.smartstate.ems.util.IsEquals;
import com.smartstate.ems.util.IsNullObject;
import com.smartstate.ems.util.StringUtils;
import com.smartstate.ems.entity.*;
import com.smartstate.ems.mapper.*;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.beans.IntrospectionException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class EquipmentImpl extends ServiceImpl<EquipmentMapper, Equipment> implements EquipmentService {

    @Autowired
    EquipmentConfigMapper equipmentConfigMapper;

    @Autowired
    EquipmentMapper equipmentMapper;

    @Resource
    private ObjMiddleMapper objMiddleMapper;

    @Resource
    private ObjMoudelMapper objMoudelMapper;

    @Resource
    private EquipmentTypeMapper equipmentTypeMapper;

    @Resource
    private IQuartzJobService iQuartzJobService;


    @Resource
    private QuartzMapper quartzMapper;

    /**
     * 选中的楼和下面所有的子楼层
     */
    HashSet<ObjMoudel> objects = new HashSet<>();


    private Map<String, Object> objectMap = null;

    private Map<String, Object> deviceIdMap = null;

    /**
     * 分页查询设备
     *
     * @param pageDTO
     * @return
     */
    @Override
    public Page<Equipment> queryAllPageByDTO(PageDTO pageDTO) {
        Equipment dto = (Equipment) pageDTO.getDto();
        //创建查询语句包装器和分页查询表对象
        Page<Equipment> page = new Page(pageDTO.getPage(), pageDTO.getSize());
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("createTime");
        Page<Equipment> equipmentPage = baseMapper.selectPage(page, queryWrapper);
        List<Equipment> selectEnd = new ArrayList<>();
        long totlal = 0l;

        //选择楼层
        try {
            if (!IsNullObject.isNullObject(dto) && dto.getObjId() != null && !"".equals(dto.getObjId())) {
                //根据楼宇id查询
                //递归查询选中的楼和下面所有的子楼层
                objects.clear();
                selectByParentId(dto.getObjId());
                List<String> list = objects.stream().map(ObjMoudel::getId).collect(Collectors.toList());

                //楼层设备中间对象集合
                ArrayList<ObjMiddle> objMiddles = new ArrayList<>();
                list.stream().forEach(objId -> {
                    List<ObjMiddle> objMiddleList = objMiddleMapper.selectByObjId(objId);
                    objMiddles.addAll(objMiddleList);
                });
                List<Equipment> equipmentList = equipmentMapper.findAll();

                for (ObjMiddle objMiddle : objMiddles) {
                    equipmentList.stream().filter(equipment -> equipment.getDeviceId().equals(objMiddle.getDeviceId())).findAny().ifPresent(selectEnd::add);
                }

                HashSet<Equipment> recores = new HashSet<>();
                //选择楼层并且要根据名称查询
                if (dto.getName() != null && !"".equals(dto.getName())) {
                    if (CollectionUtil.isNotEmpty(selectEnd)) {
                        //根据设备名模糊查询
                        for (Equipment equipment : selectEnd) {
                            int[] ints = getkmpNext(equipment.getName());
                            int kmp = kmp(equipment.getName(), ((Equipment) pageDTO.getDto()).getName(), ints);
                            if (kmp != -1) {
                                recores.add(equipment);
                            }
                        }
                    }
                }
                //选择楼层并且要根据设备类型查询
                if (dto.getType() != null && !"".equals(dto.getType())) {
                    if (CollectionUtil.isNotEmpty(selectEnd)) {
                        //根据设备类型查询
                        for (Equipment equipment : selectEnd) {
                            if (equipment.getType().equals(dto.getType())) {
                                recores.add(equipment);
                            }
                        }
                    }
                }
                //选择楼层并且要根据名称查询并且也要根据类型查询
                if (dto.getName() != null && !"".equals(dto.getName()) && dto.getType() != null && !"".equals(dto.getType())) {
                    List<Equipment> collect = recores.stream().filter(equipment -> equipment.getType().equals(dto.getType()))
                            .filter(equipment -> IsEquals.isEquals(equipment.getName(),dto.getName())).collect(Collectors.toList());
                    recores.clear();
                    recores.addAll(collect);
                }
                if ((dto.getName() != null && !"".equals(dto.getName())) || (dto.getType() != null && !"".equals(dto.getType()))) {
                    selectEnd.clear();
                }
                selectEnd.addAll(recores);
                totlal = selectEnd.size();
            }
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        }

        try {
            if (!IsNullObject.isNullObject(dto) && dto.getObjId() == null) {
                if (dto.getName() != null && !"".equals(dto.getName())) {
                    queryWrapper.and(wrapper -> wrapper.like("name", dto.getName()));
                }
                if (dto.getType() != null && !"".equals(dto.getType())) {
                    queryWrapper.and(wrapper -> wrapper.eq("type", dto.getType()));
                }
                equipmentPage = baseMapper.selectPage(page, queryWrapper);
                selectEnd.clear();
                selectEnd.addAll(equipmentPage.getRecords());
                totlal = equipmentPage.getTotal();
            }
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        }

        //默认分页
        try {
            if (IsNullObject.isNullObject(dto)) {//判断dto是否为空对象

                equipmentPage = baseMapper.selectPage(page, queryWrapper);
                //每个设备构造三种建模对象
                extracted(equipmentPage.getRecords());
                return equipmentPage;
            }
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        }


        equipmentPage.setTotal(totlal);
        int offset = (int) ((pageDTO.getPage() - 1) * pageDTO.getSize());
        selectEnd = selectEnd.subList(offset, selectEnd.size() > (int) (offset + pageDTO.getSize()) ? (int) (offset + pageDTO.getSize()) : selectEnd.size());
        equipmentPage.setRecords(selectEnd);


        //构造三种建模对象
        extracted(selectEnd);

        //返回分页查询结果
        //根据创建时间倒序
        List<Equipment> collect = equipmentPage.getRecords().stream().sorted(Comparator.comparing(Equipment::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
        equipmentPage.setRecords(collect);
        equipmentPage.setTotal(equipmentPage.getRecords().size());
        return equipmentPage;
    }

    private void extracted(List<Equipment> selectEnd) {
        //查询空间结构中的所有objId
        objectMap = objMoudelMapper.queryAllObjId("1");
        //查询所有设备对应空间建模的所有objId
        deviceIdMap = objMoudelMapper.queryAllDeviceIdFitAllObjId("1");


        for (Equipment record : selectEnd) {
            //三种对象集id合
            List<String> stringList = objMiddleMapper.findByDeviceId(record.getDeviceId());
            for (String s : stringList) {
                //空间管理
                ObjMoudel nameByIdAndType = objMoudelMapper.findNameByIdAndType(s, "1");
                if (nameByIdAndType != null) {

                    //进行名称拼接
                    String objId  = String.valueOf(((Map) deviceIdMap.get(record.getDeviceId())).get("objId"));
                    Map<String, Object> map = (Map) objectMap.get(objId);
                    String objIdName = "";
                    while(true){
                        objIdName = objIdName == "" ? map.get("name") + objIdName : map.get("name") + "-" + objIdName;
                        if ("0".equals(map.get("parentId"))){
                            break;
                        }
                        map = (Map) objectMap.get(map.get("parentId"));
                    }
                    nameByIdAndType.setName(objIdName);
                    record.setSpace(nameByIdAndType);

                }
                //成本中心
                ObjMoudel nameByIdAndType1 = objMoudelMapper.findNameByIdAndType(s, "3");
                if (nameByIdAndType1 != null) {
                    record.setCostOf(nameByIdAndType1);
                }
                //组织结构
                ObjMoudel nameByIdAndType2 = objMoudelMapper.findNameByIdAndType(s, "2");
                if (nameByIdAndType2 != null) {
                    record.setOrganization(nameByIdAndType2);
                }

            }
            //构造设备类型对象
            String s = equipmentTypeMapper.selectByDeviceId(record.getType());
            EquipmentType equipmentType = new EquipmentType();
            equipmentType.setType(record.getType().toString());
            equipmentType.setName(s);
            record.setEquipmentType(equipmentType);

            //构造设备采集方式
            EquipmentConfiguration equipmentConfiguration = equipmentConfigMapper.selectOne(record.getDeviceId());
            if (equipmentConfiguration != null && equipmentConfiguration.getWay() != null && !"".equals(equipmentConfiguration.getWay())) {
                record.setWay(equipmentConfiguration.getWay());
            }
        }
    }


    /**
     * 递归查询选中的楼下和下面所有的子楼层
     */
    public void selectByParentId(String objId) {
        ObjMoudel objIdAndType = objMoudelMapper.findObjIdAndType(objId, "1");
        if (objIdAndType != null) {
            objects.add(objIdAndType);
            List<ObjMoudel> childModelList = objMoudelMapper.selectByParentId(objIdAndType.getId());
            if (childModelList != null && childModelList.size() > 0) {
                objects.addAll(childModelList);
                childModelList.stream().forEach(chile -> {
                    selectByParentId(chile.getId());
                });
            }
        }
    }

    /**
     * 新增或修改设备
     *
     * @param equipmentDTO
     * @return
     */
    @Override
    public boolean save(EquipmentDTO equipmentDTO) throws Exception {
        boolean save = false;
        //新增设备，判断是否有数据重复
        if (equipmentDTO.getId() == null) {
            //判断设备编码是否重复
            Integer count = getByDeviceId(equipmentDTO.getDeviceId());
            if (count > 0) {
                throw new MyRException(ErrorEnums.CUSTOM_DEVICEID);
            }
            //判断设备名称是否重复
            Integer equipmentMapperByName = equipmentMapper.getByName(equipmentDTO.getName());
            if (equipmentMapperByName > 0) {
                throw new MyRException(ErrorEnums.CUSTOM_DEVICENAME);
            }

            Equipment equipment = new Equipment();
            BeanUtils.copyProperties(equipmentDTO, equipment);
            String id = IdUtil.simpleUUID();
            equipment.setId(id);
            save = this.saveOrUpdate(equipment);
            if (save) {
                //在设备表添加一条数据
                EquipmentConfiguration equipmentConfiguration = new EquipmentConfiguration();
                equipmentConfiguration.setId(IdUtil.simpleUUID());
                equipmentConfiguration.setDeviceId(equipmentDTO.getDeviceId());
                equipmentConfiguration.setType(equipmentDTO.getType());
                equipmentConfiguration.setWay(equipmentDTO.getWay());
                int insert = equipmentConfigMapper.insert(equipmentConfiguration);
                if (insert > 0) {
                    //设备添加成功，就套用模板，添加设备属性
                    addEquipmentConfig(equipmentDTO.getDeviceId(), equipmentDTO.getType().toString());
                }

                // 如果是plc采集方式，就定时去Redis中读取设备的上下限
                if (equipmentDTO.getWay() != null && "plc".equals(equipmentDTO.getWay())) {
                    extracted(equipmentDTO, id);
                }
            }

        } else {
            //编辑设备
            //判断设备编码是否重复
            if (!equipmentDTO.getDeviceId().equals(equipmentDTO.getBeforeDeviceId())) {
                Integer count = getByDeviceId(equipmentDTO.getDeviceId());
                if (count > 0) {
                    throw new MyRException(ErrorEnums.CUSTOM);
                }
            }
            //判断设备名称是否重复
            if (!equipmentDTO.getName().equals(equipmentDTO.getBeforeName())) {
                Integer count = equipmentMapper.getByName(equipmentDTO.getName());
                if (count > 0) {
                    throw new MyRException(ErrorEnums.CUSTOM);
                }
            }
            Equipment equipment = new Equipment();
            BeanUtils.copyProperties(equipmentDTO, equipment);
            save = this.saveOrUpdate(equipment);

            //修改成功了，就把设备属性表里的采集方式也修改一下
            if (save) {
                //设备id修改了，定时任务也要修改
                if (!equipmentDTO.getDeviceId().equals(equipmentDTO.getBeforeDeviceId())) {
                    List<QuartzJob> quartzJob = quartzMapper.findByJobName(equipmentDTO.getBeforeDeviceId());
                    quartzJob.stream().forEach(job -> {
                        job.setJobName(equipmentDTO.getDeviceId());
                        try {
                            iQuartzJobService.updateJob(job);
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    });

                }
                //这个设备是否在属性表里有数据
                EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(equipmentDTO.getBeforeDeviceId());
                //采集方式有改变
                if (configuration != null) {
                    String way = configuration.getWay();
                    configuration.setDeviceId(equipmentDTO.getDeviceId());
                    configuration.setType(equipmentDTO.getType());
                    //有就修改采集方式
                    configuration.setWay(equipmentDTO.getWay());
                    int updateById = equipmentConfigMapper.updateById(configuration);
                    // 采集方式修改了，那么设备定时读取上下限的方式也会变
                    if (updateById > 0 && !equipmentDTO.getWay().equals(way) && "plc".equals(equipmentDTO.getWay())) {
                        //从盒子采集，变成plc采集，就要添加一个定时任务去读取设备的上下限
                        extracted(equipmentDTO, equipmentDTO.getId());
                    } else if (updateById > 0 && !equipmentDTO.getWay().equals(way) && !"plc".equals(equipmentDTO.getWay())) {
                        //从plc采集，变成盒子采集，就要把这个定时任务删掉
                        //根据定时器分组和定时器名称查询
                        QuartzJob quartzJob = quartzMapper.findQuartzByGroupAndName("ACQUISITIONMETHODS", equipmentDTO.getDeviceId());
                        if (quartzJob != null) {
                            iQuartzJobService.deleteJob(quartzJob);
                        }
                    }

                } else { //这个修改的设备在属性表了没有保存记录
                    //在设备表添加一条数据
                    EquipmentConfiguration equipmentConfiguration = new EquipmentConfiguration();
                    equipmentConfiguration.setId(IdUtil.simpleUUID());
                    equipmentConfiguration.setDeviceId(equipmentDTO.getDeviceId());
                    equipmentConfiguration.setType(equipmentDTO.getType());
                    equipmentConfiguration.setWay(equipmentDTO.getWay());
                    equipmentConfigMapper.insert(equipmentConfiguration);
                    // 是plc采集方式就添加一个定时任务去读取设备属性的上下限
                    if ("plc".equals(equipmentDTO.getWay())) {
                        extracted(equipmentDTO, equipmentDTO.getId());
                    }
                }
            }
        }
        //如果传入主键id  就说明是修改  就把以前的数据删掉
        if (equipmentDTO.getId() != null) {
            objMiddleMapper.deleteByDeviceId(equipmentDTO.getBeforeDeviceId());
        }
        //空间管理
        if (equipmentDTO.getSpace() != null) {
            objMiddleMapper.save(equipmentDTO.getSpace(), equipmentDTO.getDeviceId());
        }
        //组织管理
        if (equipmentDTO.getOrganization() != null) {
            objMiddleMapper.save(equipmentDTO.getOrganization(), equipmentDTO.getDeviceId());
        }
        //成本管理
        if (equipmentDTO.getCostOf() != null) {
            objMiddleMapper.save(equipmentDTO.getCostOf(), equipmentDTO.getDeviceId());
        }

        //设备编码改变，dataId也会改变
        if (equipmentDTO.getId() != null && !equipmentDTO.getDeviceId().equals(equipmentDTO.getBeforeDeviceId())) {
            EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(equipmentDTO.getBeforeDeviceId());
            if (configuration != null) {
                ArrayList<EquipmentDTO.AddressData> addressData1 = new ArrayList<>();
                if ((configuration.getTags() != null)) {
                    for (EquipmentDTO.AddressData addressData : JSONArray.parseArray(configuration.getTags().toString(), EquipmentDTO.AddressData.class)) {
                        String dataId = equipmentDTO.getDeviceId() + "." + addressData.getAttributeName();
                        addressData.setDataId(dataId);
                        addressData1.add(addressData);
                    }
                    String s = JSON.toJSONString(addressData1);
                    configuration.setTags(s);
                }
                configuration.setDeviceId(equipmentDTO.getDeviceId());
                equipmentConfigMapper.updateById(configuration);
            }
        }
        return save;
    }

    //新增采集设备属性上下限的定时任务
    private void extracted(EquipmentDTO equipmentDTO, String id) throws Exception {
        QuartzJob quartzJob = new QuartzJob();
        quartzJob.setJobName(equipmentDTO.getDeviceId());//定时器的名称
        quartzJob.setJobGroup("ACQUISITIONMETHODS");//定时器的分组
        quartzJob.setInvokeTarget("quartz.PLCCollect('" + id + "')");//定时器执行的方法
        quartzJob.setCronExpression("0/1 * * * * ?");//采集周期
        quartzJob.setMisfirePolicy(ScheduleConstants.MISFIRE_IGNORE_MISFIRES);//立即执行
        quartzJob.setConcurrent("1");//是否允许并发执行
        quartzJob.setStatus("0");//状态
        quartzJob.setRemark("定时读取" + equipmentDTO.getDeviceId() + "设备的属性上下限");//备注
        iQuartzJobService.insertJob(quartzJob);
    }

    /**
     * 添加设备附加属性
     *
     * @param equipmentDTO
     * @return
     */
    @Override
    public Boolean additionalAttribute(EquipmentDTO equipmentDTO) {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setPrettyPrinting();
        Gson gson = gsonBuilder.create();
        String additionalAttributes = equipmentDTO.getAdditionalAttribute();
        if (additionalAttributes.isEmpty()) {
            return false;
        }
        List<Map> list = gson.fromJson(additionalAttributes, List.class);
        List<Object> values = list.stream().map((item) -> item.values()).collect(Collectors.toList());
        additionalAttributes = StringUtils.join(values, "").replace("[", "")
                .replace("]", "").replace(",", "").replace(" ", "");
        if (additionalAttributes.isEmpty()) {
            return false;
        }
        Equipment equipment = new Equipment();
        equipment.setDeviceId(equipmentDTO.getDeviceId());
        BeanUtils.copyProperties(equipmentDTO, equipment);
        equipment.setAdditionalAttribute(equipmentDTO.getAdditionalAttribute());
        return equipmentMapper.updateByDeviceId(equipment);
    }

    /**
     * 根据设备类型查设备
     *
     * @param type
     * @return
     */
    @Override
    public List<Equipment> selectEquipment(String type) {
        return equipmentMapper.selectEquipment(type);
    }

    /**
     * 根据id删除设备
     *
     * @param id
     * @return
     * @throws SchedulerException
     */
    @Override
    public boolean removeDeviceById(String id) throws SchedulerException {
        Equipment one = equipmentMapper.selectById(id);
        boolean b = this.removeById(id);
        objMiddleMapper.deleteByDeviceId(one.getDeviceId());
        equipmentConfigMapper.deleteByDeviceId(one.getDeviceId());
        equipmentMapper.deleteAlarm(one.getDeviceId());
        //删除设备，如果该设备有定时任务，那么定时任务也要删除
        List<QuartzJob> quartzJobs = quartzMapper.selectByJobName(one.getDeviceId());
        if (!CollectionUtils.isEmpty(quartzJobs)) {
            quartzJobs.stream().forEach(job -> {
                try {
                    iQuartzJobService.deleteJob(job);
                } catch (SchedulerException e) {
                    throw new RuntimeException(e);
                }
            });

        }
        return b;
    }

    /**
     * 查询所有设备中类型是工业看板的设备
     *
     * @return
     */
    @Override
    public List<Equipment> selectEquipmentType() {
        return equipmentMapper.selectEquipmentType();
    }

    /**
     * 根据设备编码检查数据库中是否存在这条数据
     *
     * @param deviceId
     * @return
     */
    public Integer getByDeviceId(String deviceId) {
        return equipmentMapper.getByCode(deviceId);

    }


    /**
     * 设备属性模板
     *
     * @param deviceId
     */
    public void addEquipmentConfig(String deviceId, String type) {
        switch (type) {
            case "1":
                addSortingConfig(deviceId);
                break;
            case "2":
                addElectricMeterConfig(deviceId);
                break;
            case "3":
                addWaterMeterConfig(deviceId);
                break;
            case "4":
                addSteamConfig(deviceId);
                break;
            case "5":
                addGasConfig(deviceId);
                break;
        }
    }


    /**
     * 添加的是工业看板，就直接在设备属性表里面添加数据
     *
     * @param deviceId
     */
    public void addSortingConfig(String deviceId) {
        EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(deviceId);
        //构造设备属性的tags
        ArrayList<EquipmentDTO.AddressData> addressDataArrayList = new ArrayList<>();
        EquipmentDTO.AddressData addressData = new EquipmentDTO.AddressData();
        addressData.setAttributeName("temperature");
        addressData.setAttributeAlias("温度");
        addressData.setDataId(deviceId + "." + addressData.getAttributeName());
        addressData.setIsAlarm("0");
        addressData.setEnabled(true);
        addressDataArrayList.add(addressData);

        EquipmentDTO.AddressData addressData1 = new EquipmentDTO.AddressData();
        addressData1.setAttributeName("humidity");
        addressData1.setAttributeAlias("湿度");
        addressData1.setDataId(deviceId + "." + addressData1.getAttributeName());
        addressData1.setIsAlarm("0");
        addressData.setEnabled(true);
        addressDataArrayList.add(addressData1);

        EquipmentDTO.AddressData addressData2 = new EquipmentDTO.AddressData();
        addressData2.setAttributeName("longParticle");
        addressData2.setAttributeAlias("尘埃粒子5");
        addressData2.setDataId(deviceId + "." + addressData2.getAttributeName());
        addressData2.setIsAlarm("0");
        addressData.setEnabled(true);
        addressDataArrayList.add(addressData2);

        EquipmentDTO.AddressData addressData3 = new EquipmentDTO.AddressData();
        addressData3.setAttributeName("littleParticle");
        addressData3.setAttributeAlias("尘埃粒子0.5");
        addressData3.setDataId(deviceId + "." + addressData3.getAttributeName());
        addressData3.setIsAlarm("0");
        addressData.setEnabled(true);
        addressDataArrayList.add(addressData3);

        EquipmentDTO.AddressData addressData4 = new EquipmentDTO.AddressData();
        addressData4.setAttributeName("staticPressure");
        addressData4.setAttributeAlias("静压");
        addressData4.setDataId(deviceId + "." + addressData4.getAttributeName());
        addressData4.setIsAlarm("0");
        addressData.setEnabled(true);
        addressDataArrayList.add(addressData4);

        EquipmentDTO.AddressData addressData5 = new EquipmentDTO.AddressData();
        addressData5.setAttributeName("dewPoint");
        addressData5.setAttributeAlias("露点");
        addressData5.setDataId(deviceId + "." + addressData5.getAttributeName());
        addressData5.setIsAlarm("0");
        addressData.setEnabled(true);
        addressDataArrayList.add(addressData5);

        String tags = JSON.toJSONString(addressDataArrayList);
        configuration.setTags(tags);
        configuration.setAlarmtone("true");
        equipmentConfigMapper.updateById(configuration);

    }

    /**
     * 添加的是电表，就直接在设备属性表里面添加数据
     */
    public void addElectricMeterConfig(String deviceId) {
        EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(deviceId);
        //构造设备属性的tags
        ArrayList<EquipmentDTO.AddressData> addressDataArrayList = new ArrayList<>();
        EquipmentDTO.AddressData addressData = new EquipmentDTO.AddressData();
        addressData.setAttributeName("activeEnergy");
        addressData.setAttributeAlias("有功电能");
        addressData.setDataId(deviceId + "." + addressData.getAttributeName());
        addressData.setIsDifference("1");
        addressData.setPostProcessing("差值计算");
//        addressData.setEnabled(true);
        addressDataArrayList.add(addressData);

        EquipmentDTO.AddressData addressData1 = new EquipmentDTO.AddressData();
        addressData1.setAttributeName("reactiveEnergy");
        addressData1.setAttributeAlias("无功电能");
        addressData1.setDataId(deviceId + "." + addressData1.getAttributeName());
        addressData1.setIsDifference("1");
        addressData1.setPostProcessing("差值计算");
//        addressData1.setEnabled(true);
        addressDataArrayList.add(addressData1);

        EquipmentDTO.AddressData addressData2 = new EquipmentDTO.AddressData();
        addressData2.setAttributeName("apparentEnergy");
        addressData2.setAttributeAlias("视在能量");
        addressData2.setDataId(deviceId + "." + addressData2.getAttributeName());
        addressData2.setIsDifference("1");
        addressData2.setPostProcessing("差值计算");
//        addressData2.setEnabled(true);
        addressDataArrayList.add(addressData2);

        String tags = JSON.toJSONString(addressDataArrayList);
        configuration.setTags(tags);
        equipmentConfigMapper.updateById(configuration);

    }

    /**
     * 添加的是水表，就直接在设备属性表里面添加数据
     */
    public void addWaterMeterConfig(String deviceId) {
        EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(deviceId);
        //构造设备属性的tags
        ArrayList<EquipmentDTO.AddressData> addressDataArrayList = new ArrayList<>();
        EquipmentDTO.AddressData addressData = new EquipmentDTO.AddressData();
        addressData.setAttributeName("instantaneous");
        addressData.setAttributeAlias("瞬间计量");
        addressData.setDataId(deviceId + "." + addressData.getAttributeName());
        addressData.setIsDifference("1");
        addressData.setPostProcessing("差值计算");
//        addressData.setEnabled(true);
        addressDataArrayList.add(addressData);

        EquipmentDTO.AddressData addressData1 = new EquipmentDTO.AddressData();
        addressData1.setAttributeName("total");
        addressData1.setAttributeAlias("总计");
        addressData1.setDataId(deviceId + "." + addressData1.getAttributeName());
        addressData1.setIsDifference("1");
        addressData1.setPostProcessing("差值计算");
//        addressData1.setEnabled(true);
        addressDataArrayList.add(addressData1);

        String tags = JSON.toJSONString(addressDataArrayList);
        configuration.setTags(tags);
        equipmentConfigMapper.updateById(configuration);

    }

    /**
     * 添加的是水蒸汽表，就直接在设备属性表里面添加数据
     */
    public void addSteamConfig(String deviceId) {
        EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(deviceId);
        //构造设备属性的tags
        ArrayList<EquipmentDTO.AddressData> addressDataArrayList = new ArrayList<>();
        EquipmentDTO.AddressData addressData = new EquipmentDTO.AddressData();
        addressData.setAttributeName("instantaneous");
        addressData.setAttributeAlias("瞬间计量");
        addressData.setDataId(deviceId + "." + addressData.getAttributeName());
        addressData.setIsDifference("1");
        addressData.setPostProcessing("差值计算");
//        addressData.setEnabled(true);
        addressDataArrayList.add(addressData);

        EquipmentDTO.AddressData addressData1 = new EquipmentDTO.AddressData();
        addressData1.setAttributeName("total");
        addressData1.setAttributeAlias("总计");
        addressData1.setDataId(deviceId + "." + addressData1.getAttributeName());
        addressData1.setIsDifference("1");
        addressData1.setPostProcessing("差值计算");
//        addressData1.setEnabled(true);
        addressDataArrayList.add(addressData1);

        String tags = JSON.toJSONString(addressDataArrayList);
        configuration.setTags(tags);
        equipmentConfigMapper.updateById(configuration);

    }

    /**
     * 添加的是天然气表，就直接在设备属性表里面添加数据
     */
    public void addGasConfig(String deviceId) {
        EquipmentConfiguration configuration = equipmentConfigMapper.selectOne(deviceId);
        //构造设备属性的tags
        ArrayList<EquipmentDTO.AddressData> addressDataArrayList = new ArrayList<>();
        EquipmentDTO.AddressData addressData = new EquipmentDTO.AddressData();
        addressData.setAttributeName("instantaneous");
        addressData.setAttributeAlias("瞬间计量");
        addressData.setDataId(deviceId + "." + addressData.getAttributeName());
        addressData.setIsDifference("1");
        addressData.setPostProcessing("差值计算");
//        addressData.setEnabled(true);
        addressDataArrayList.add(addressData);

        EquipmentDTO.AddressData addressData1 = new EquipmentDTO.AddressData();
        addressData1.setAttributeName("total");
        addressData1.setAttributeAlias("总计");
        addressData1.setDataId(deviceId + "." + addressData1.getAttributeName());
        addressData1.setIsDifference("1");
        addressData1.setPostProcessing("差值计算");
//        addressData1.setEnabled(true);
        addressDataArrayList.add(addressData1);

        String tags = JSON.toJSONString(addressDataArrayList);
        configuration.setTags(tags);
        equipmentConfigMapper.updateById(configuration);

    }


    /**
     * 模糊比较两个字符串  返回-1，比较失败，返回别的，比较成功
     *
     * @param str1
     * @param str2
     * @param next
     * @return
     */
    int kmp(String str1, String str2, int[] next) {
        int i1 = -1;
        for (int i = 0, j = 0; i < str1.length(); ++i) {

            while (j > 0 && str1.charAt(i) != str2.charAt(j)) {
                j = next[j - 1];
            }

            if (str1.charAt(i) == str2.charAt(j)) {
                j++;
            }

            if (j == str2.length()) {
                return i - j + 1;
            }
        }
        return -1;
    }


    /**
     * @return dest的部分匹配表
     */
    private static int[] getkmpNext(String dest) {
        int length = dest.length();
        int[] next = new int[length];
        next[0] = 0;

        for (int i = 1, j = 0; i < length; i++) {

            while (j > 0 && dest.charAt(i) != dest.charAt(j)) {
                j = next[j - 1];
            }

            if (dest.charAt(i) == dest.charAt(j)) {
                j++;
            }
            next[i] = j;
        }
        return next;
    }
}